package pers.ree.demo.concurrent;

public class VolatileDemo {

    public boolean withoutVolatileFound = false;

    // 静态变量或者成员变量都需要加volatile才能执行到"笔来了，开始写字。。。"
    public volatile boolean found = false;
//    public volatile static boolean found = false;


    public static void main(String[] args) {
        // 不使用volatile的demo
//        withoutVolatileDemo();

        // 成员变量使用volatile的demo
        volatileDemo();


        // 下面的代码纯粹只是为了测试内部类的成员变量是否可以用volatile修饰
        InnerTest1 innerTest1 = new VolatileDemo().new InnerTest1();
        innerTest1.a = 1;
        System.out.println(innerTest1.a);

        InnerTest2 innerTest2 = new VolatileDemo.InnerTest2();
        innerTest2.b = 2;
        System.out.println(innerTest2.b);
    }

    public static void withoutVolatileDemo() {
        final VolatileDemo demo = new VolatileDemo();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("等基友送笔来。。。");

                long startTimeMillis = System.currentTimeMillis();
                long time = 0;

                // 等待
                while (!demo.withoutVolatileFound) {
                    time = System.currentTimeMillis() - startTimeMillis;
                    if (time > 5000) {
                        // 同一个线程用的是同一个虚拟机栈，所以demo.withoutVolatileFound的修改不加volatile也可见
                        demo.withoutVolatileFound = true;
                        System.out.println("time: " + time + "，等不到基友自己买笔了。。。");
                    }
                }

                System.out.println("笔来了，开始写字。。。");
            }
        }, "我线程").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("基友找到笔了，送过去。。。");
                // 如果withoutVolatileFound不加volatile，则本线程的修改对"我线程"不可见
                demo.withoutVolatileFound = true;
            }
        }, "基友线程").start();
    }

    public static void volatileDemo() {
        final VolatileDemo demo = new VolatileDemo();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("等基友送笔来。。。");

                // 等待
                while (!demo.found) {
                }

                System.out.println("笔来了，开始写字。。。");
            }
        }, "我线程").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("基友找到笔了，送过去。。。");
                // 如果found不加volatile，则本线程的修改对"我线程"不可见
                demo.found = true;
            }
        }, "基友线程").start();
    }

    class InnerTest1 {
        public volatile int a;
    }

    static class InnerTest2 {
        public volatile int b;
    }
}
